/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package test;

import alg.EvaluationDerived;
import entities.*;
import java.util.*;
import org.jgap.*;
import org.jgap.Configuration;
import util.*;
import static alg.Constants.*;

/**
 *
 * @author Dragan Sahpaski
 */
public class QE_EvolveDerived {

    String log;
    String summary;

    /**
     * The total number of times we'll let the population evolve.
     */
    public QE_EvolveDerived(String testName, Domain domain,
            int evolutions, int populationSize,
            String queriesFileName, String oldDomainFileName, String domainFileName,
            double allowedMaintenanceCost, double allowedDerivationCost, double rho)
            throws Exception {

        String evolve = "Evolve Derived";
        String start = "\nStart: " + new Date();
        log = "\nEvolutions: " + evolutions + "\nPopulation size: " + populationSize + "\nold domain: " + oldDomainFileName + "\ndomain: " + domainFileName + "\nqueries: " + queriesFileName + "\nallowedMaintenanceCost: " + allowedMaintenanceCost + "\nallowedDerivationCost " + allowedDerivationCost + "\nrho: " + rho;
        Domain oldDomain = Utils.loadDomain(oldDomainFileName);
        List<Query> queries = QueryUtils.loadQueries(queriesFileName, domain);
        //log += Printing.printViews(domain);
        //log += Printing.printRelations(domain);
        EvaluationDerived evaluation = new EvaluationDerived(
                new DwConfigurationDerived(domain, oldDomain, queries, allowedMaintenanceCost, rho, allowedDerivationCost));
        Configuration conf = Utils.getDefaultConfiguration(populationSize, evaluation);
        Genotype population = Utils.getRandomGenotype(conf);

        log += "\n";
        System.out.println(log);
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < evolutions; i++) {
            population.evolve();
            String text = "\nEvolution " + (i + 1) + ": " + MAX_VALUE + " " + population.getFittestChromosome().getFitnessValue() + " " + (MAX_VALUE - population.getFittestChromosome().getFitnessValue());
            log += text;
            System.out.print(text);
        }
        long endTime = System.currentTimeMillis();
        log += "Total evolution time: " + (endTime - startTime) + " ms";
        // System.out.println(Printing.printChromosome(domain, queries, population.getFittestChromosome()));
        log += "\nTotal evolution time: " + (endTime - startTime) + " ms";
        log = start + "\nEnd: " + new Date() + "\n" + log;

        List<IChromosome> chromosomes = population.getFittestChromosomes(populationSize);
        double bestQE = alg.Constants.MAX_VALUE;
        IChromosome bestChromosome = null;
        for (IChromosome c : chromosomes) {
            c.getGene(evaluation.getDomain().getViewGraph().getRoot().getTableIndex()).setAllele(new Boolean(true));
            evaluation.getDomain().calculateTableVariants(c);
            evaluation.evaluate();
            if (evaluation.getViewMaintenanceCost() <= allowedMaintenanceCost) {
                if (evaluation.getQueryExecutionCost() < bestQE) {
                    bestChromosome = c;
                    bestQE = evaluation.getQueryExecutionCost();
                }
            }
        }

        if (bestChromosome == null) {
            String msg = "\nNO SOLUTION FOUND";
            System.out.println(msg);
            log += msg;
            population.getFittestChromosome().getGene(evaluation.getDomain().getViewGraph().getRoot().getTableIndex()).setAllele(new Boolean(true));
            evaluation.getDomain().calculateTableVariants(population.getFittestChromosome());
            evaluation.evaluate();
            Utils.saveDomain(domainFileName, domain);

            summary = testName + " Summary: queryCost:" + evaluation.getQueryExecutionCost() + " maintCost:" + evaluation.getViewMaintenanceCost() + "derivationCost:" + evaluation.getDerivationCost() + " totalCost:" + evaluation.getTotalCost();
            System.out.println("\n\t" + summary);
            log = evolve + "\n" + summary + "\n" + start + "\nEnd: " + new Date() + "\n" + log;

        } else {
            bestChromosome.getGene(evaluation.getDomain().getViewGraph().getRoot().getTableIndex()).setAllele(new Boolean(true));
            evaluation.getDomain().calculateTableVariants(bestChromosome);
            evaluation.evaluate();
            Utils.saveDomain(domainFileName, domain);

            summary = testName + " Summary: queryCost:" + evaluation.getQueryExecutionCost() + " maintCost:" + evaluation.getViewMaintenanceCost() + "derivationCost:" + evaluation.getDerivationCost() + " totalCost:" + evaluation.getTotalCost();
            System.out.println("\n\t" + summary);
            log = evolve + "\n" + summary + "\n" + start + "\nEnd: " + new Date() + "\n" + log;
        }
    }
    private static final int MAX_ALLOWED_EVOLUTIONS = 50;
    private static final int POPULATION_SIZE = 20;
    private static final String QUERIES_FILE_NAME = "queries/queries75.txt";
    private static final String OLD_DOMAIN_FILENAME = "domain100.txt";
    private static final String DOMAIN_FILENAME = "domain75.txt";
    private static final double ALLOWED_MAINT_COST = 150000.0;
    private static final double ALLOWED_DERIVATION_COST = ALLOWED_MAINT_COST * 0.5;
    private static final double RHO = 0.2;

    public QE_EvolveDerived(String testName, Domain domain, String queriesFileName, String olDomainFileName, String domainFileName) throws Exception {
        this(testName, domain, MAX_ALLOWED_EVOLUTIONS, POPULATION_SIZE, queriesFileName, olDomainFileName, domainFileName, ALLOWED_MAINT_COST, ALLOWED_DERIVATION_COST, RHO);
    }

    public QE_EvolveDerived() throws Exception {
        this("QE_EvolutionDerived", new ISDV1().getDomain(), MAX_ALLOWED_EVOLUTIONS, POPULATION_SIZE, QUERIES_FILE_NAME, OLD_DOMAIN_FILENAME, DOMAIN_FILENAME, ALLOWED_MAINT_COST, ALLOWED_DERIVATION_COST, RHO);
    }

    public String getLog() {
        return log;
    }

    public String getSummary() {
        return summary;
    }

    public static void main(String[] args) throws Exception {
        new QE_EvolveDerived();
    }
}







